package pack;
import java.util.Hashtable;


public class PairwiseGlobalAlignment {
	
	
	/******************************************************************************
	 * Modified pairwise global alignment of Project One.
	 * It needs two sequences, a score matrix and gap costs as input.
	 * 
	 * !!NOTE!!
	 * Just holds the alignment matrix D in memory, this means no traceback is possible
	 */
	
	/**
	 * CONSTRUCTOR
	 */
	PairwiseGlobalAlignment(Hashtable<String,Hashtable<String,String>> scoMat,String is1,String is2,int gap){
	
		scoreMatrix = scoMat;	
		setGapScore(gap);
		
		seq1=is1;
		seq2=is2;		
		alignmentMatrix  = new int[seq1.length()+1][seq2.length()+1];
		computeOptimalAlignment();	
	}
	
	
	/**
	 * DESTRUCTOR
	 * @return 
	 */
	protected void finalize(){
		
	}
	
	
	private String seq1; // Sequence 1
	private String seq2; // Sequence 2	

	private int gapCost = -1;
		
	private Hashtable<String,Hashtable<String,String>> scoreMatrix;
	
	private int[][] alignmentMatrix;	
	
	
	/**
	 *  Setter-Methods
	 */
	
	public void setGapScore(int score){gapCost=score;}
		
	
	
	
	/**
	 * Getter Methods
	 */
	
	public int getValueInAlignmentMatrix(int i,int j){
		return alignmentMatrix[i][j];
	}
	
	
	
	/**
	 * This function returns the score for two characters from a given score matrix 
	 */	
	public int matchScore(char a,char b){		

			String score 	= ((Hashtable<String,String>) scoreMatrix.get(""+a)).get(""+b).toString();
			return Integer.parseInt(score);		
	}
	
	/**
	 * Computes the optimal global alignment of two sequences.
	 * Input parameters are global variables from above.
	 */
	
	public void computeOptimalAlignment(){
		
		int n = seq1.length();
		int m = seq2.length();
		
		
		// Initialization
		for(int i = 0; i<=n; i++){
			alignmentMatrix[i][0] = i*gapCost;
		}
		for(int j = 0; j<=m; j++){
			alignmentMatrix[0][j] = j*gapCost;
		}
		
		
		// Filling up the table
		for(int i = 1; i<=n;i++){
			
			for(int j = 1; j<=m;j++){				
				alignmentMatrix[i][j] = Math.min(
											Math.min(
													alignmentMatrix[i-1][j] + gapCost,
													alignmentMatrix[i][j-1] + gapCost
											),
													alignmentMatrix[i-1][j-1] + matchScore(seq1.charAt(i-1),seq2.charAt(j-1))
									);
			}
		}	
		
				
	}	
	
}
